home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Technical Documentation / Sample Code / DTS.Lib & Samples / DTS.Lib / =Using TextEditControl.c < prev    next >
Encoding:
Text File  |  1992-10-22  |  19.4 KB  |  390 lines  |  [TEXT/MPS ]

  1. ***** TextEditControl.c usage documentation *****/
  2.  
  3. Purpose:  To simplify TextEdit handling within a window.
  4.  
  5. Implementing a TextEdit control does the following:
  6.  
  7. 1) Makes using TextEdit in a non-dialog window easy.
  8. 2) The TERecord is automatically associated with the window, since
  9.    it is in the window's control list.
  10. 3) The TextEdit control can have scrollbars associated with it, and these
  11.    are also kept in the window's control list, and also associated with
  12.    the TextEdit control.
  13. 4) Updating of the TERecord is much simpler, since all that is
  14.    necessary is to draw the control (or all the window's controls with
  15.    a DrawControls call).
  16. 5) What isn't handled automatically by tracking the control can be handled
  17.    with a direct call.  There are simple calls to handle TextEdit events.
  18. 6) Undo is already supported.
  19. 7) A TERecord length can be specified.  This length will not be exceeded
  20.    when editing the TERecord.
  21. 8) When you close the window, the TERecord is disposed of.
  22.    (This automatic disposal can easily be defeated.)
  23.  
  24.  
  25. To create a TextEdit control, you only need a single call.  For example:
  26.  
  27.     mode = cteVScrollLessGrow;    /* TERecord read-write, with vertical scroll         */
  28.                                 /* that leaves space for grow box.                     */
  29.  
  30.     CTENew(rViewCtl,            /* Resource ID of view control for TextEdit control. */
  31.            window,                /* Window to hold TERecord.                             */
  32.            &teHndl,                /* Return handle for TERecord.                         */
  33.            &ctlRect,            /* Rect for TextEdit view control.                     */
  34.            &destRect,            /* destRect for TERecord                             */
  35.            &viewRect,            /* viewRect for TERecord                             */
  36.            &brdrRect,            /* Used to frame a border.                             */
  37.            32000,                /* Max size for TERecord text.                         */
  38.            mode);
  39.  
  40. The various choices for the TextEdit control are defined as follows:
  41.  
  42. #define cteReadOnly            1
  43. #define cteHScroll            2
  44. #define cteHScrollLessGrow    6
  45. #define cteVScroll            8
  46. #define cteVScrollLessGrow    24
  47. #define cteActive            32
  48. #define cteShowActive        64
  49. #define cteTabSelectAll        128
  50. #define cteTwoStep            256
  51.  
  52. cteReadOnly:        Don't allow editing.  When selected, don't blink a caret.
  53.                     Allow text selection and copy-to-clipboard.
  54. cteHScroll:            Create and manage a horizontal scrollbar for the TextEdit control.
  55. cteHScrollLessGrow:    Create and manage a horizontal scrollbar for the TextEdit control,
  56.                     but leave space for a growIcon on the right end of the scrollbar.
  57. cteVScroll:            Create and manage a vertical scrollbar for the TextEdit control.
  58. cteVScrollLessGrow:    Create and manage a vertical scrollbar for the TextEdit control,
  59.                     but leave space for a growIcon on the bottom end of the scrollbar.
  60. cteActive:            Make this the initially active control for the window.
  61. cteShowActive:        When the control is active, show that it is by drawing a selection
  62.                     border around the control.  This is the new 7.0 human-interface
  63.                     method of showing which control is active.  (This can be an important
  64.                     indicator because if you have readOnly TextEdit controls, they don't
  65.                     have a blinking caret.  If they also don't have any text selected,
  66.                     there will be no indication that it is the active control.
  67. cteTabSelectAll:    When using IsCtlEvent() (discussed under "! using CtlHandler.c"),
  68.                     tab changes the active TextEdit (or List) control.  When a TextEdit
  69.                     control is made active, sometimes it is desirable to initially select
  70.                     all of the text for the user.  Setting this bit accomplishes this.
  71. cteTwoStep:            When using IsCtlEvent(), you may want the initial click on a TextEdit
  72.                     control to just select the control, or you may wish the click to start
  73.                     tracking in addition to selecting the control.  The tracking is
  74.                     considered the second step, so by setting this bit, you will get
  75.                     tracking of the control on the initial click.
  76.  
  77. Simply initialize ctlRect, destRect, viewRect, and brdrRect appropriately, and
  78. then call CTENew (which stands for Control TENew).  If teHndl is returned
  79. nil, then CTENew failed.  Otherwise, you now have a TextEdit control in the
  80. window.  If it fails, it also returns an error stating why it failed
  81. (memFullErr or resNotFound).
  82.  
  83. NOTE: There is a TextEdit bug (no way!!) such that you may need to set the
  84.       viewRect right edge 2 bigger than the right edge of destRect.  If you
  85.       do not do this, then there will be some clipping on the right edge in
  86.       some cases.  Of course, you may want this.  You may want horizontal
  87.       scrolling, and therefore you would want the destRect substantially
  88.       larger than the viewRect.  If you don't want horizontal scrolling,
  89.       then you probably don't want any clipping horizontally, and therefore
  90.       you will need to set destRect.right 2 less than viewRect.right.
  91.  
  92.  
  93. If the CTENew call succeeds, you then have a TextEdit control in your
  94. window.  It will be automatically disposed of when you close the window.
  95. If you don't waht this to happen, then you can detach it from the
  96. view control which owns it.  To do this, you would to the following:
  97.  
  98.     viewCtl = CTEViewFromTE(theTextEditHndl);
  99.     if (viewCtl) SetCRefCon(viewCtl, nil);
  100.  
  101. The view control keeps a reference to the TERecord in the refCon.
  102. If the refCon is cleared, then the view control does nothing.  So, all that
  103. is needed to detach a TERecord from a view control is to set the
  104. view control's refCon nil.  Now if you close the window, you will still
  105. have the TERecord.
  106.  
  107.  
  108. To remove a TextEdit control completely from a window, you make one call:
  109.  
  110.     CTEDispose(theTextEditHndl);
  111.  
  112. This disposes of the TERecord, the view control, and any scrollbar
  113. controls that were created when the TextEdit control was created with
  114. the call CTENew.
  115.  
  116.  
  117. Events for TERecord are handled nearly automatically.  You can
  118. make one of 3 calls:
  119.  
  120.     CTEClick(eventPtr, &action);
  121.     CTEEvent(eventPtr, &action);
  122.     CTEKey(eventPtr);
  123.  
  124. In each case, if the event was handled, true is returned.  CTEEvent simply
  125. calls either CTEClick or CTEKey, whichever is appropriate.
  126.  
  127.  
  128. Another call you will want to use is CTEEditMenu.  This is used to set the
  129. state of cut/copy/paste/clear for TextEdit controls.  It checks the active
  130. control to see if text is selected, if the control is read-only, etc.
  131. Based on this information, it sets cut/copy/paste/clear either active
  132. or inactive.  If any menu items are set active, it returns true.
  133.  
  134.  
  135. One more high-level call is CTEUndo().  In response to an undo menu item
  136. being selected by the user, just call CTEUndo(), and the edits the user
  137. has made will be undone.  (This includes undoing an undo.)
  138.  
  139.  
  140. The last high-level call for managing the edit menu is CTEClipboard.  Call it
  141. when you want to do a cut/copy/paste/clear for the active TextEdit control.
  142. The value to pass is as follows:
  143.  
  144.  2: cut
  145.  3: copy
  146.  4: paste
  147.  5: clear
  148.  
  149. These are the same values you would pass to a DA for these actions.
  150.  
  151.  
  152.  
  153. Here is a list of the functions and a description as to their purpose:
  154.  
  155. void            CTEActivate(Boolean active, TEHandle teHndl);
  156.     /* Activate this TextEdit record.  If another is currently active, deactivate
  157.     ** that one.  The view control for this TextEdit record is also flagged to
  158.     ** indicate which was the last active one for this window.  If the previous
  159.     ** active TextEdit record was in the same window, then flag the old one off
  160.     ** for this window.  The whole point for this per-window flagging is so that
  161.     ** activate events can reactivate the correct TextEdit control per window. */
  162.  
  163. Boolean            CTEClick(EventRecord *event, short *action);
  164.     /* This is called when a mouseDown occurs in the content of a window.  It
  165.     ** returns true if the mouseDown caused a TextEdit action to occur.  Events
  166.     ** that are handled include if the user clicks on a scrollbar that is
  167.     ** associated with a TextEdit control.
  168.     **
  169.     ** if CTEClick returns false, action is 0
  170.     ** if CTEClick returns true,  action is:
  171.     **      -1 if control was activated by clicking on the TextEdit control or related scrollbar.
  172.     **       0 if control that was clicked on was already active. */
  173.  
  174.  
  175. void            CTEClipboard(short menuID);
  176.     /* Do the cut/copy/paste/clear operations for the currently active
  177.     ** TextEdit control.  Caller assumes appropriateness of the call.  Typically,
  178.     ** this routine won't be called at an inappropriate time, since the menu
  179.     ** item should be enabled or disabled correctly.
  180.     ** Use CTEEditMenu to set the menu items undo/cut/copy/paste/clear correctly
  181.     ** for the active TextEdit control.  Since undo isn't currently supported,
  182.     ** all that CTEEditMenu does for the undo case is to deactivate it right now. */
  183.  
  184. ControlHandle    CTECtlHit(void);
  185.     /* The TextEdit control that was hit by calling FindControl is saved in a
  186.     ** global variable, since the CDEF has no way of returning what kind it was.
  187.     ** To determine that it was a TextEdit control that was hit, first call this
  188.     ** function.  The first call returns the old value in the global variable,
  189.     ** plus it resets the global to nil.  Then call FindControl(), and then
  190.     ** call this function again.  If it returns nil, then a TextEdit control
  191.     ** wasn't hit.  If it returns non-nil, then it was a TextEdit control that
  192.     ** was hit, and specifically the one returned. */
  193.  
  194. void            CTEDispose(TEHandle teHndl);
  195.     /* Disposes of the TERecord, TextEdit control, and any related scrollbars. */
  196.  
  197. TEHandle        CTEDisposeView(ControlHandle viewCtl);
  198.     /* Dispose of the view control and related scrollbars.  This function also
  199.     ** returns the handle to the TextEdit record, since it was just orphaned.
  200.     ** Use this function if you want to get rid of a TextEdit control, but you
  201.     ** want to keep the TextEdit record. */
  202.  
  203. short            CTEDocHeight(TEHandle teHndl);
  204.     /* Returns the full document height. */
  205.  
  206. Boolean            CTEEditMenu(Boolean *activeItem, short editMenu, short undoID, short cutID);
  207.     /* Enable or disable edit menu items based on the active TextEdit control.
  208.     ** You pass the menu ID of the undo item in undoID, and the menu ID of the
  209.     ** cut item in cutID.  If undoID or cutID is non-zero, then some action is
  210.     ** performed.  If you pass a non-zero value for cutID, then the other menu
  211.     ** items cut/copy/paste/clear are updated to reflect the status of the
  212.     ** active TextEdit control. */
  213.  
  214. Boolean            CTEEvent(EventRecord *event, short *action);
  215.     /* Handle the event if it applies to the active TextEdit control.  If some
  216.     ** action occured due to the event, return true.
  217.     **
  218.     ** if event not handled, false is returned and action is 0
  219.     ** if event handled, true is returned and action is:
  220.     **      -1: an inactive control was clicked on and it was made active.
  221.     **       0: an active control was clicked on and tracked.
  222.     **       1: the control took the keypress, but no change occured to the TERecord.
  223.     **       2: the control took the keypress and the TERecord changed. */
  224.  
  225. void            CTEFakeClick(short newStart, short newEnd, Boolean extend, TEHandle teHndl);
  226.     /* Select or reselect a range of text without flashing or lurching. */
  227.  
  228. TEHandle        CTEFindActive(WindowPtr window);
  229.     /* Returns the active TextEdit control, if any.  If nil is passed in, then
  230.     ** the return value represents whatever TextEdit control is active, independent
  231.     ** of what window it is in.  If a window is passed in, then it returns a
  232.     ** TextEdit control only if the active control is in the specified window.
  233.     ** If the active TextEdit control is in some other window, then nil is returned. */
  234.  
  235. Boolean            CTEFindCtl(WindowPtr window, EventRecord *event, TEHandle *teHndl, ControlHandle *ctlHit);
  236.     /* This determines if a TextEdit control was clicked on directly.  This does
  237.     ** not determine if a related scrollbar was clicked on.  If a TextEdit
  238.     ** control was clicked on, then true is returned, as well as the TextEdit
  239.     ** handle and the handle to the view control. */
  240.  
  241. TEHandle        CTEFromScroll(ControlHandle scrollCtl, ControlHandle *retCtl);
  242.     /* Find the TextEdit record that is related to the indicated scrollbar. */
  243.  
  244. void            CTEHide(TEHandle teHndl);
  245.     /* Hide the designated TextEdit control and related scrollbars. */
  246.  
  247. void            CTEIdle(void);
  248.     /* Blink the caret in the active TextEdit control.  The active TextEdit
  249.     ** control may be read-only, in which case the caret does not blink. */
  250.  
  251. short            CTEKey(EventRecord *event);
  252.     /* See if the keypress event applies to the TextEdit control, and if it does,
  253.     ** handle it and return non-zero.
  254.     **
  255.     ** if CTEKey returns 0, TextEdit control didn't handle the event.
  256.     ** if CTEKey returns 1, TextEdit control did handle the event, but the TERecord didn't change.
  257.     ** if CTEKey returns 2, TextEdit control did handle the event, and the TERecord changed.
  258.  
  259. void            CTEMove(TEHandle teHndl, short newH, short newV);
  260.     /* This function is used to move a TextEdit control.  Pass it the TextEdit
  261.     ** record to move, plus the new position.  It will move the TextEdit control,
  262.     ** along with any scrollbars the control may have.  All areas that need
  263.     ** updating are cleared and invalidated. */
  264.  
  265. OSErr            CTENew(short viewID, WindowPtr window, TEHandle *teHndl, Rect *cRect,
  266.                        Rect *dRect, Rect *vRect, Rect *bRect, short maxTextLen, short mode);
  267.     /* Create a new TextEdit control.  See the comments at the beginning of this
  268.     ** file for more information. */
  269.  
  270. void            CTENewUndo(ControlHandle viewCtl, Boolean alwaysNewUndo);
  271.     /* Save the data (if appropriate) so that user can undo. */
  272.  
  273. ControlHandle    CTENext(WindowPtr window, TEHandle *teHndl, ControlHandle ctl);
  274.     /* Get the next TextEdit control in the window.  You pass it a control handle
  275.     ** for the view control, or nil to start at the beginning of the window.
  276.     ** It returns both a TextEdit handle and the view control handle for that
  277.     ** TextEdit record.  If none is found, nil is returned.  This allows you to
  278.     ** repeatedly call this function and walk through all the TextEdit controls
  279.     ** in a window. */
  280.  
  281. short            CTENumTextLines(TEHandle teHndl);
  282.     /* Return the number of lines of text.  This is because there is a bug in
  283.     ** TextEdit where the number of lines returned is incorrect if the text
  284.     ** ends with a c/r.  This function adjusts for this bug. */
  285.  
  286. short            CTENumViewLines(TEHandle teHndl);
  287.     /* Return the number of text lines in the view area. */
  288.  
  289. OSErr            CTEPrint(TEHandle teHndl, short *offset, Rect *rct);
  290.     /* Use this function to print the contents of a TextEdit record.  Pass it a
  291.     ** TextEdit handle, a pointer to a text offset, and a pointer to a rect to
  292.     ** print the text in.  The offset should be initialized to what character
  293.     ** in the TextEdit record you wish to start printing at (most likely 0).
  294.     ** The print function prints as much text as will fit in the rect, and
  295.     ** then updates the offset to tell you what is the first character that didn't
  296.     ** print.  You can then call the print function again with another rect with
  297.     ** this new offset, and it will print the text starting at the new offset.
  298.     ** This method is very useful when a single TextEdit record is longer than a
  299.     ** single page, and you wish the text to break at the end of the page.
  300.     ** The bottom of rect is also updated, along with the offset.  The bottom edge
  301.     ** of the rect is changed to reflect the actual bottom of the text printed.
  302.     ** This is useful because the rect passed in didn't necessarily hold an
  303.     ** integer number of lines of text.  The bottom of the rect is adjusted so
  304.     ** it exactly holds complete lines of text.
  305.     ** It is also possible that the rect could hold substantially more lines of
  306.     ** text than there are remaining.  Again, in this situation, the bottom of
  307.     ** rect is adjusted so that the rect tightly bounds the text printed.
  308.     ** The remaining piece of information passed back is an indicator that the
  309.     ** text through the end of the TextEdit record was printed.  When the end
  310.     ** of the text is reached, the offset for the next text to be printed is
  311.     ** returned as -1.  This indicates that processing of the TextEdit record
  312.     ** is complete. */
  313.  
  314. Boolean            CTEReadOnly(TEHandle teHndl);
  315.     /* Return if the TextEdit control is read/write (true) or read-only (false). */
  316.  
  317. ControlHandle    CTEScrollFromTE(TEHandle teHndl, Boolean vertScroll);
  318.     /* Return the control handle for the TextEdit control's scrollbar, either
  319.     ** vertical or horizontal.  If the scrollbar doesn't, nil is returned. */
  320.  
  321. ControlHandle    CTEScrollFromView(ControlHandle viewCtl, Boolean vertScroll);
  322.     /* Return the control handle for the scrollbar related to the view control,
  323.     ** either horizontal or vertical.  If the scrollbar doesn't exist, return nil. */
  324.  
  325. void            CTESetKeyFilter(TEHandle teHndl, CTEKeyFilterProcPtr proc);
  326.     /* A TextEdit control can have an optional key filter, which is called whenever
  327.     ** CTEKey() is called.  If you pass in nil, then the filtering is turned off.
  328.     ** This allows individual TextEdit controls to handle their own filtering.
  329.     ** The filter procedure is of the form:
  330.     **     Boolean (*CTEKeyFilterProcPtr)(TEHandle teHndl, EventRecord *event, Boolean *handled);
  331.     ** If true is returned, then CTEKey() is aborted, and the value in "handled" is
  332.     ** returned.  By having a separate abort value and return value, you can determine
  333.     ** if processing of the event should be continued or not, independent of whether
  334.     ** or not you aborted CTEKey(). */
  335.  
  336. void            CTESetSelect(short start, short end, TEHandle teHndl);
  337.     /* Select a range of text.  TESetSelect can't be used alone because it doesn't
  338.     ** update the scrollbars.  This function calls TESetSelect, and then fixes up
  339.     ** the scrollbars. */
  340.  
  341. void            CTEShow(TEHandle teHndl);
  342.     /* Show the designated TextEdit control and related scrollbars. */
  343.  
  344. void            CTESize(TEHandle teHndl, short dx, short dy, Boolean newDest);
  345.     /* This function is used to resize a TextEdit control.  Pass it the TextEdit
  346.     ** record to resize, plus the new horizontal and vertical size.  It will
  347.     ** resize the TextEdit control, realign the text, if necessary, plus it will
  348.     ** resize and adjust any scrollbars the TextEdit control may have.  All areas
  349.     ** that need updating are cleared and invalidated. */
  350.  
  351. Handle            CTESwapText(TEHandle teHndl, Handle newText, Boolean update);
  352.     /* Swap the TextEdit text handle with the text handle passed in. */
  353.  
  354. WindowPtr        CTETargetInfo(TEHandle *teHndl, Rect *teView);
  355.     /* Return information for the currently active TextEdit control.  The currently
  356.     ** active TextEdit control is stored in gActiveTEHndl, and can be accessed
  357.     ** directly.  If gActiveTEHndl is nil, then there is no currently active one.
  358.     ** The information that we return is the viewRect and window of the active
  359.     ** TextEdit control.  This is information that could be gotten directly, but
  360.     ** this call makes it a little more convenient. */
  361.  
  362. void            CTEUndo(void);
  363.     /* Perform an undo function for the TextEdit control. */
  364.  
  365. void            CTEUpdate(TEHandle teHndl, ControlHandle ctl, Boolean justShowActive);
  366.     /* Draw the TextEdit control and frame. */
  367.  
  368. ControlHandle    CTEViewFromTE(TEHandle teHndl);
  369.     /* Return the control handle for the view control that owns the TextEdit
  370.     ** record.  Use this to find the view to do customizations such as changing
  371.     ** the update procedure for this TextEdit control. */
  372.  
  373. Boolean            CTEWindActivate(WindowPtr window);
  374.     /* Call this when a window with TextEdit controls is being activated.  This
  375.     ** will make the TextEdit control that was last active in this window the
  376.     ** active TextEdit control again.  If it can't find one that was the last
  377.     ** active control, it makes the first one it finds the active control. */
  378.  
  379. void            CTEAdjustTEBottom(TEHandle teHndl);
  380.     /* This function is called after an edit to make sure that there is no extra
  381.     ** white space at the bottom of the viewRect.  If there are blank lines at
  382.     ** the bottom of the viewRect, and there is text scrolled off the top of the
  383.     ** viewRect, then the TextEdit control is scrolled to fill this space, or as
  384.     ** much of it as possible. */
  385.  
  386. void            CTEAdjustScrollValues(TEHandle teHndl);
  387.     /* Bring the scrollbar values up to date with the current document position
  388.     ** and length. */
  389.  
  390.